---@diagnostic disable: inject-field
---@class data_insertobj_locale 植入物本地化
---@field cn string
---@field en string

---@class data_insertobj 单个植入物
---@field name data_insertobj_locale 本地化表
---@field inspect data_insertobj_locale|nil 检视
---@field recipe_desc data_insertobj_locale|nil 配方描述
---@field ingres table<string, number> 配方
---@field unlock string|table|function 解锁
---@field noimg boolean|nil 是则目前还没有做图片
---@field prefabs table|nil 需要提前加载的预制物
---@field onequip fun(inst: ent, container: ent, owner: ent, params)
---@field onunequip fun(inst: ent, container: ent, owner: ent, params)
---@field onsave nil|fun(inst: ent, sav_data: table)
---@field onload nil|fun(inst: ent, sav_data: table)

---@alias data_insertobjs table<string, data_insertobj> 植入物表

---@type data_insertobjs
local data = {}

--[[
data.prefab = {
    name = "兔腿",
    unlock = {                      --解剖生物
        "rabbit",
    },
    ingres = {                      --材料
        rabbit = 1,
    },
    onequip = function(inst, container, owner) end,
    onunequip = function(inst, container, owner) end,
}
]]

---植入物是否被插入
---@param inst ent
---@return ent|nil
local function isInserted(inst)
    local owner = inst.components.inventoryitem and inst.components.inventoryitem.owner
    if owner and owner.prefab == 'kkd_fleshsack' and owner.components.container and owner.components.inventoryitem then
        local player = owner.components.inventoryitem.owner
        if player and player.prefab == 'kukude' then
            return player
        end
    end
    return nil
end

---comment
---@param tbl table
---@param ind string
---@param val any
---@param fn function|nil
local function initsth(tbl, ind, val, fn, ...)
    if tbl[ind] == nil then
        tbl[ind] = val 
        if fn then
            return fn(...)
        end
    end
end

---@param gem PrefabID
---@param num number
local function iscrabkingwith(gem, num)
    return function(target)
        if not target.prefab == "crabking" then return false end 
        local n = 0
        for _, g in pairs(target.socketed or {}) do 
            if g.itemprefab == gem then n = n + 1 end 
        end
        return n >= num
    end
end

---兔腿
data.io_rabbitleg = {
    name = {cn = "兔腿", en = 'Rabbit Leg'},
    inspect = {cn = "俗话说“动如脱兔”。", en = 'This rabbit leg seems to hold endless energy, wearing it will boost your speed to new heights!'},
    recipe_desc = {cn = "切下来时兔子必须还活着。", en = 'Made from a live rabbit, this leg provides additional speed boosts.'},
    unlock = "rabbit",
    ingres = {
        rabbit = 1,
    },
    onequip = function(inst, container, owner, params) 
        owner.components.locomotor:SetExternalSpeedMultiplier(container, params.name, params.tun.SPEED_MULT ^ math.clamp(params.num, 0, params.tun.COUNT_LIMIT))
    end,
    onunequip = function(inst, container, owner, params) 
        owner.components.locomotor:SetExternalSpeedMultiplier(container, params.name, params.tun.SPEED_MULT ^ math.clamp(params.num, 0, params.tun.COUNT_LIMIT))
    end,
    --noimg = false,
}

---发条义肢
data.io_clockwork = {
    name = {cn = "发条义肢", en = 'Clockwork Prosthesis'},
    inspect = {cn = "如果要装这个，我原来的腿怎么办？", en = 'The mechanical power of this prosthesis grants unparalleled speed, wear it and you become the lightning knight on the battlefield!'},
    recipe_desc = {cn = "血肉苦弱，机械飞升！", en = 'A clockwork prosthesis made from two gears, significantly increasing the wearer\'s movement speed.'},
    unlock = {
        "rook",
        "rook_nightmare",
    },
    ingres = {
        gears = 2,
    },
    onequip = function(inst, container, owner, params) 
        owner.components.locomotor:SetExternalSpeedMultiplier(container, params.name, params.tun.SPEED_MULT ^ math.clamp(params.num, 0, params.tun.COUNT_LIMIT))
    end,
    onunequip = function(inst, container, owner, params) 
        owner.components.locomotor:SetExternalSpeedMultiplier(container, params.name, params.tun.SPEED_MULT ^ math.clamp(params.num, 0, params.tun.COUNT_LIMIT))
    end,
    --noimg = false,
}

---外置大脑
data.io_outbrain = {
    name = {cn = "外置大脑", en = 'External Brain'},
    inspect = {cn = "能隐约听到里面传来嗡鸣声……", en = 'This external brain seems to have its own consciousness, it significantly increases your sanity limit, keeping you calm in chaos!'},
    recipe_desc = {cn = "普通的外置处理单元。", en = 'An external brain made from moonbutterfly wings, increasing the wearer\'s sanity limit.'},
    unlock = "moonbutterfly",
    ingres = {
        moonbutterflywings = 1,
    },
    onequip = function(inst, container, owner, params) 
        owner.components.sanity.max = owner.components.sanity.max + params.tun.SANITY_MAX
        owner.components.sanity:DoDelta(0)
    end,
    onunequip = function(inst, container, owner, params) 
        owner.components.sanity.max = owner.components.sanity.max - params.tun.SANITY_MAX
        owner.components.sanity:DoDelta(0)
    end,
    noimg = false,
}

---外置大脑PLUS
data.io_outbrain_plus = {
    name = {cn = "外置大脑PLUS", en = 'External Brain PLUS'},
    inspect = {cn = "温暖而微微蠕动，正如预期。", en = 'An upgraded external brain, not only increasing your sanity limit but also providing a sanity regeneration rate of 1.33 per minute, keeping your mind always clear!'},
    recipe_desc = {cn = "优秀的外置处理单元。", en = 'An External Brain PLUS made from two yellow gems and an external brain, increasing the wearer\'s sanity limit and providing a sanity regeneration rate of 1.33 per minute.'},
    unlock = iscrabkingwith("yellowgem", 2),
    ingres = {
        io_outbrain = 1,
        yellowgem = 2,
    },
    onequip = function(inst, container, owner, params) 
        owner.components.sanity.max = owner.components.sanity.max + params.tun.SANITY_MAX
        owner.components.sanity:DoDelta(0)
        container.components.equippable.dapperness = container.components.equippable.dapperness + params.tun.DAPPERNESS
    end,
    onunequip = function(inst, container, owner, params) 
        owner.components.sanity.max = owner.components.sanity.max - params.tun.SANITY_MAX
        owner.components.sanity:DoDelta(0)
        container.components.equippable.dapperness = container.components.equippable.dapperness - params.tun.DAPPERNESS
    end,
    noimg = false,
}

---外置大脑ULTRA
data.io_outbrain_ultra = {
    name = {cn = "外置大脑ULTRA", en = 'External Brain ULTRA'},
    inspect = {cn = "瞠目于光中！", en = 'The ultimate external brain, not only increasing your sanity limit but also providing a sanity regeneration rate of 3.3 per minute, keeping your mind at peak performance!'},
    recipe_desc = {cn = "完美的外置处理单元！", en = 'An External Brain ULTRA made from two alterguardian hat shards and an external brain PLUS, increasing the wearer\'s sanity limit and providing a sanity regeneration rate of 3.3 per minute.'},
    unlock = "alterguardian_phase3",
    ingres = {
        alterguardianhatshard = 2,
        io_outbrain_plus = 1,
    },
    onequip = function(inst, container, owner, params) 
        owner.components.sanity.max = owner.components.sanity.max + params.tun.SANITY_MAX
        owner.components.sanity:DoDelta(0)
        container.components.equippable.dapperness = container.components.equippable.dapperness + params.tun.DAPPERNESS
    end,
    onunequip = function(inst, container, owner, params) 
        owner.components.sanity.max = owner.components.sanity.max - params.tun.SANITY_MAX
        owner.components.sanity:DoDelta(0)
        container.components.equippable.dapperness = container.components.equippable.dapperness - params.tun.DAPPERNESS
    end,
    noimg = false,
}

---增生心脏
data.io_heart = {
    name = {cn = "增生心脏", en = 'Proliferative Heart'},
    inspect = {cn = "真是三心二意。", en = 'This proliferative heart seems to be brimming with vitality, it significantly increases your health limit, making your life force more resilient!'},
    recipe_desc = {cn = "备用要害，多多益善。", en = 'A proliferative heart made from two pieces of monster meat, increasing the wearer\'s health limit.'},
    unlock =
    {
        "hound",
        "moonhound"
    },
    ingres = {
        monstermeat = 2,
    },
    onequip = function(inst, container, owner, params) 
        owner.components.health.maxhealth = owner.components.health.maxhealth + params.tun.HEALTH_MAX
        owner.components.health:ForceUpdateHUD(true)
    end,
    onunequip = function(inst, container, owner, params) 
        owner.components.health.maxhealth = owner.components.health.maxhealth - params.tun.HEALTH_MAX
        owner.components.health:ForceUpdateHUD(true)
    end,
    noimg = false,
}

---强化增生心脏
data.io_heart_enhanced = {
    name = {cn = "强化增生心脏", en = 'Proliferative Heart Enhanced'},
    inspect = {cn = "我真的还有必要留着原来那颗吗？", en = 'An enhanced proliferative heart, not only increasing the health limit but also making the wearer\'s life force more indestructible!'},
    recipe_desc = {cn = "帝王引擎，启动！", en = 'An Enhanced Proliferative Heart made from two red gems and a proliferative heart, increasing the wearer\'s health limit.'},
    unlock = iscrabkingwith("redgem", 2),
    ingres = {
        redgem = 2,
        io_heart = 1,
    },
    onequip = function(inst, container, owner, params) 
        owner.components.health.maxhealth = owner.components.health.maxhealth + params.tun.HEALTH_MAX
        owner.components.health:ForceUpdateHUD(true)
    end,
    onunequip = function(inst, container, owner, params) 
        owner.components.health.maxhealth = owner.components.health.maxhealth - params.tun.HEALTH_MAX
        owner.components.health:ForceUpdateHUD(true)
    end,
    noimg = false,
}

---瘤胃
data.io_ingluvies = {
    name = {cn = "瘤胃", en = 'Rumen'},
    inspect = {cn = "反刍动物的第一个胃，主要用于储存食物。", en = 'This rumen seems to possess infinite digestive capacity, it significantly increases your hunger limit, making your hunger disappear without a trace!'},
    recipe_desc = {cn = "消化不掉就先存起来。", en = 'A rumen made from two pieces of meat, increasing the wearer\'s hunger limit.'},
    unlock = "beefalo",
    ingres = {
        meat = 2,
    },
    onequip = function(inst, container, owner, params) 
        owner.components.hunger.max = owner.components.hunger.max + params.tun.HUNGER_MAX
    end,
    onunequip = function(inst, container, owner, params) 
        owner.components.hunger.max = owner.components.hunger.max - params.tun.HUNGER_MAX
    end,
    noimg = false,
}

---重瓣胃
data.io_omasum = {
    name = {cn = "重瓣胃", en = 'Omasum'},
    inspect = {cn = "反刍动物的第三个胃，用于磨碎食物及吸收水分。", en = 'This omasum not only increases your hunger limit but also allows you to regain an additional 5% hunger when eating, completely eradicating your hunger!'},
    recipe_desc = {cn = "在肚子里也能细嚼慢咽。", en = 'An omasum made from a slurper pelt and a rumen, increasing the wearer\'s hunger limit and allowing for an additional 5% hunger recovery when eating.'},
    unlock = "slurper",
    ingres = {
        slurper_pelt = 1,
        io_ingluvies = 1,
    },
    onequip = function(inst, container, owner, params) 
        owner.components.hunger.max = owner.components.hunger.max + params.tun.HUNGER_MAX
        owner.components.eater.hungerabsorption = owner.components.eater.hungerabsorption * params.tun.HUNGER_MULT
    end,
    onunequip = function(inst, container, owner, params) 
        owner.components.hunger.max = owner.components.hunger.max - params.tun.HUNGER_MAX
        owner.components.eater.hungerabsorption = owner.components.eater.hungerabsorption / params.tun.HUNGER_MULT
    end,
    noimg = false,
}

---皱胃
data.io_abomasum = {
    name = {cn = "皱胃", en = 'Abomasum'},
    inspect = {cn = "反刍动物的第四个胃，最终消化食物。", en = 'This abomasum not only increases your hunger limit but also allows you to regain an additional 5% hunger and 5% health when eating, completely curing your hunger and injuries!'},
    recipe_desc = {cn = "完全消化，彻底吸收。", en = 'An abomasum made from bear fur and an omasum, increasing the wearer\'s hunger limit and allowing for an additional 5% hunger and 5% health recovery when eating.'},
    unlock = {
        "bearger",
        "mutatedbearger"
    },
    ingres = {
        bearger_fur = 1,
        io_omasum = 1,
    },
    onequip = function(inst, container, owner, params) 
        owner.components.hunger.max = owner.components.hunger.max + params.tun.HUNGER_MAX
        owner.components.eater.hungerabsorption = owner.components.eater.hungerabsorption * params.tun.HUNGER_MULT
        owner.components.eater.healthabsorption = owner.components.eater.healthabsorption * params.tun.HEALTH_MULT
    end,
    onunequip = function(inst, container, owner, params) 
        owner.components.hunger.max = owner.components.hunger.max - params.tun.HUNGER_MAX
        owner.components.eater.hungerabsorption = owner.components.eater.hungerabsorption / params.tun.HUNGER_MULT
        owner.components.eater.healthabsorption = owner.components.eater.healthabsorption / params.tun.HEALTH_MULT
    end,
    noimg = false,
}

local function dofreezeattack(owner, data)
    if math.random() > owner.kkd_freeze then return end 
    local target = data.target 
    if not target then return end 
    if target.components.freezable ~= nil and target:IsValid() then
        target.components.freezable:AddColdness(1)
        target.components.freezable:SpawnShatterFX()
    end
end

---冰冷之触
data.io_coldtouch = {
    name = {cn = "冰冷之触", en = 'A Cold Touch'},
    inspect = {cn = "触之生寒", en = 'A Cold Touch seems to possess freezing power, each attack has a 10% chance to freeze enemies, making your foes tremble uncontrollably!'},
    recipe_desc = {cn = "死亡般的冰冷。", en = 'An A Cold Touch made from two pieces of monster meat and four pieces of ice, providing a 10% chance to freeze enemies on attack.'},
    unlock = "icehound",
    ingres = {
        monstermeat = 2,
        ice = 4,
    },
    onequip = function(inst, container, owner, params) 
        initsth(owner, "kkd_freeze", 0, function ()
            owner:ListenForEvent("onhitother", dofreezeattack)
        end)
        owner.kkd_freeze = owner.kkd_freeze + params.tun.FREEZE_PR
    end,
    onunequip = function(inst, container, owner, params) 
        owner.kkd_freeze = owner.kkd_freeze - params.tun.FREEZE_PR
        if owner.kkd_freeze <= 0 then 
            owner.kkd_freeze = nil
            owner:RemoveEventCallback("onhitother", dofreezeattack)
        end
    end,
    noimg = false,
}


---冰封之心
data.io_frozenheart = {
    name = {cn = "冰封之心", en = 'A Cold Touch'},
    inspect = {cn = "以我的冰封之心为名！", en = 'A Cold Touch seems to possess freezing power, each attack has a 10% chance to freeze enemies, making your foes tremble uncontrollably!'},
    recipe_desc = {cn = "真正的心寒。", en = 'An A Cold Touch made from two pieces of monster meat and four pieces of ice, providing a 10% chance to freeze enemies on attack.'},
    unlock = iscrabkingwith("bluegem", 2),
    ingres = {
        bluegem = 2,
        io_coldtouch = 1,
    },
    onequip = function(inst, container, owner, params)
        initsth(owner, "kkd_freeze", 0, function ()
            owner:ListenForEvent("onhitother", dofreezeattack)
        end)
        owner.kkd_freeze = owner.kkd_freeze + params.tun.FREEZE_PR
    end,
    onunequip = function(inst, container, owner, params)
        owner.kkd_freeze = owner.kkd_freeze - params.tun.FREEZE_PR
        if owner.kkd_freeze <= 0 then
            owner.kkd_freeze = nil
            owner:RemoveEventCallback("onhitother", dofreezeattack)
        end
    end,
    noimg = false,
}


local function AddToArmy(inst, queen)
    if queen:HasTag("player") then
        queen:MakeGenericCommander()
        if inst.components.follower == nil then
            inst:AddComponent("follower")
            inst.components.follower:SetLeader(queen)
        end
    else
        if inst.components.follower ~= nil then
            inst.components.follower:StopFollowing()
            inst:RemoveComponent("follower")
        end
    end
    if queen.components.commander ~= nil then
        queen.components.commander:AddSoldier(inst)
    end
end

---蜂群信号
data.io_beesignal = {
    name = {cn = "蜂群信号", en = 'Team of Bees'},
    inspect = {cn = '它散发出一种信息素，可以用于召集和命令蜜蜂。', en = ''},
    recipe_desc = {cn = '足以让你成为蜂群的领袖。', en = ''},
    unlock = "bee",
    ingres = {
        honey = 2,
    },
    onequip = function(inst, container, owner, params) 
        owner:MakeGenericCommander()
        if owner.components.commander:GetNumSoldiers(params.tun.SOLDIER_TYPE) < params.tun.COUNT_LIMIT then 
            local x, y, z = owner.Transform:GetWorldPosition()
            local radius = TUNING.BEEGUARD_GUARD_RANGE * 0.5
            local delta_theta = PI2 / params.tun.NUM_EACH
            local bees = {}
            for i = 1, params.tun.NUM_EACH do 
                local pos_x, pos_y, pos_z = x + radius * math.cos((i-1) * delta_theta), 0, z + radius * math.sin((i-1) * delta_theta)
                bees[i] = SpawnPrefab(params.tun.SOLDIER_TYPE)
                bees[i].persists = false
                bees[i].Transform:SetPosition(pos_x, pos_y, pos_z)
                AddToArmy(bees[i], owner)
                bees[i]:AddTag("notarget")
                bees[i].components.health:SetInvincible(true)
            end
            initsth(container, "kkd_beesignal", function(owner)
                for i, bee in pairs(owner.components.commander:GetAllSoldiers(params.tun.SOLDIER_TYPE)) do 
                    owner.components.commander:RemoveSoldier(bee)
                    bee:Remove()
                end
            end,function()
                owner:ListenForEvent("kkd_despawn", container.kkd_beesignal)
            end)
        end
    end,
    onunequip = function(inst, container, owner, params) 
        if params.num > params.tun.COUNT_LIMIT/params.tun.NUM_EACH - 1 then return end 
        local bees = owner.components.commander:GetAllSoldiers(params.tun.SOLDIER_TYPE)
        for i = 1, params.tun.NUM_EACH do 
            owner.components.commander:RemoveSoldier(bees[i])
            bees[i]:Remove()
        end
    end,
    noimg = false,
}

---女王的召唤
data.io_queencall = {
    name = {cn = "女王的召唤", en = 'Call of the Queen'},
    inspect = {cn = '皇家护卫何在？', en = ''},
    recipe_desc = {cn = '为你添加一丝皇家血脉。', en = ''},
    unlock = "beequeen",
    ingres = {
        royal_jelly = 2,
    },
    onequip = function(inst, container, owner, params) 
        owner:MakeGenericCommander()
        if owner.components.commander:GetNumSoldiers(params.tun.SOLDIER_TYPE) < params.tun.COUNT_LIMIT then 
            local x, y, z = owner.Transform:GetWorldPosition()
            local radius = TUNING.BEEGUARD_GUARD_RANGE * 0.5
            local delta_theta = PI2 / params.tun.NUM_EACH
            for i = 1, params.tun.NUM_EACH do 
                local pos_x, pos_y, pos_z = x + radius * math.cos((i-1) * delta_theta), 0, z + radius * math.sin((i-1) * delta_theta)
                local bee = SpawnPrefab(params.tun.SOLDIER_TYPE)
                bee.persists = false
                bee.Transform:SetPosition(pos_x, pos_y, pos_z)
                AddToArmy(bee, owner)
                bee:AddTag("notarget")
                bee.components.health:SetInvincible(true)
            end
            initsth(container, "kkd_queencall", function(owner)
                for i, bee in pairs(owner.components.commander:GetAllSoldiers(params.tun.SOLDIER_TYPE)) do 
                    owner.components.commander:RemoveSoldier(bee)
                    bee:Remove()
                end
            end,function()
                owner:ListenForEvent("kkd_despawn", container.kkd_queencall)
            end)
        end
    end,
    onunequip = function(inst, container, owner, params) 
        if params.num > params.tun.COUNT_LIMIT/params.tun.NUM_EACH - 1 then return end 
        local bees = owner.components.commander:GetAllSoldiers(params.tun.SOLDIER_TYPE)
        for i = 1, params.tun.NUM_EACH do 
            owner.components.commander:RemoveSoldier(bees[i])
            bees[i]:Remove()
        end
    end,
    noimg = false,
}

---鳞化皮肤
data.io_scaledskin = {
    name = {cn = "鳞化皮肤", en = 'Scaly Skin'},
    inspect = {cn = '火中做自己。', en = ''},
    recipe_desc = {cn = '防火结构已构建。', en = ''},
    unlock = "dragonfly",
    ingres = {
        dragon_scales = 1,
    },
    onequip = function(inst, container, owner, params) 
        if owner.components.health ~= nil then
            owner.components.health.externalfiredamagemultipliers:SetModifier(container, math.clamp(1 - params.tun.FIREDMG_REDUCE * params.num,0,1), params.name)
        end
    end,
    onunequip = function(inst, container, owner, params) 
        if owner.components.health ~= nil then
            if params.num > 0 then
                owner.components.health.externalfiredamagemultipliers:SetModifier(container, math.clamp(1 - params.tun.FIREDMG_REDUCE * params.num,0,1), params.name)
            else
                owner.components.health.externalfiredamagemultipliers:RemoveModifier(container, params.name)
            end
        end
    end,
    noimg = false,
}

---鹅绒
data.io_velvet = {
    name = {cn = "鹅绒", en = 'Goose Down'},
    inspect = {cn = '即使不植入，也可以用来填枕头。', en = ''},
    recipe_desc = {cn = '柔软贴身。', en = ''},
    unlock = "moose",
    ingres = {
        goose_feather = 5,
    },
    onequip = function(inst, container, owner, params) 
        owner.components.temperature.inherentinsulation = owner.components.temperature.inherentinsulation + params.tun.WINTER_INSULATION
    end,
    onunequip = function(inst, container, owner, params) 
        owner.components.temperature.inherentinsulation = owner.components.temperature.inherentinsulation - params.tun.WINTER_INSULATION 
    end,
    noimg = false,
}

---防水羽毛
data.io_waterproof_feather = {
    name = {cn = "防水羽毛", en = 'Waterproof Feathers'},
    inspect = {cn = '疏水结构以及表面的油是防水的关键。', en = ''},
    recipe_desc = {cn = '油光顺滑。', en = ''},
    unlock = "penguin",
    ingres = {
        feather_crow = 5,
    },
    onequip = function(inst, container, owner, params) 
        if not container.components.waterproofer then
            container:AddComponent("waterproofer")
            container.components.waterproofer:SetEffectiveness(0)
        end
        container.components.waterproofer:SetEffectiveness(container.components.waterproofer:GetEffectiveness()+params.tun.WATER_PROOF)
    end,
    onunequip = function(inst, container, owner, params) 
        container.components.waterproofer:SetEffectiveness(container.components.waterproofer:GetEffectiveness()-params.tun.WATER_PROOF)
        if container.components.waterproofer:GetEffectiveness() <= 0 then
            container:RemoveComponent("waterproofer")
        end
    end,
    noimg = false,
}

---传说级防水羽毛
data.io_waterproof_feather_legend = {
    name = {cn = "传说级防水羽毛", en = 'Legendary Waterproof Feathers'},
    inspect = {cn = '疏水效果一流，保温效果嘛……', en = ''},
    recipe_desc = {cn = '材料越好，效果越好。', en = ''},
    unlock = "malbatross",
    ingres = {
        malbatross_feather = 5,
    },
    onequip = function(inst, container, owner, params) 
        if not container.components.waterproofer then
            container:AddComponent("waterproofer")
            container.components.waterproofer:SetEffectiveness(0)
        end
        container.components.waterproofer:SetEffectiveness(container.components.waterproofer:GetEffectiveness()+params.tun.WATER_PROOF)
        owner.components.temperature.inherentinsulation = owner.components.temperature.inherentinsulation + params.tun.WINTER_INSULATION
    end,
    onunequip = function(inst, container, owner, params) 
        container.components.waterproofer:SetEffectiveness(container.components.waterproofer:GetEffectiveness()-params.tun.WATER_PROOF)
        if container.components.waterproofer:GetEffectiveness() <= 0 then
            container:RemoveComponent("waterproofer")
        end
        owner.components.temperature.inherentinsulation = owner.components.temperature.inherentinsulation - params.tun.WINTER_INSULATION 
    end,
    noimg = false,
}

---鲨鱼皮
data.io_sharkskin = {
    name = {cn = "鲨鱼皮", en = 'Sharkskin'},
    inspect = {cn = '摸起来凉凉的……哎哟！刮到我了！', en = ''},
    recipe_desc = {cn = '以牙还牙！', en = ''},
    unlock = "shark",
    ingres = {
        fishmeat = 2,
    },
    onequip = function(inst, container, owner, params) 
        owner.components.temperature.inherentsummerinsulation = owner.components.temperature.inherentsummerinsulation + params.tun.SUMMER_INSULATION
        if not container.components.damagereflect then
            container:AddComponent("damagereflect")
            container.components.damagereflect:SetDefaultDamage(0)
        end
        container.components.damagereflect:SetDefaultDamage(container.components.damagereflect.defaultdamage + params.tun.REFLECT_DMG)
    end,
    onunequip = function(inst, container, owner, params) 
        owner.components.temperature.inherentsummerinsulation = owner.components.temperature.inherentsummerinsulation - params.tun.SUMMER_INSULATION
        container.components.damagereflect:SetDefaultDamage(container.components.damagereflect.defaultdamage - params.tun.REFLECT_DMG)
        if container.components.damagereflect.defaultdamage <= 0 and not container.components.damagereflect.reflectdamagefn then 
            container:RemoveComponent("damagereflect")
        end
    end,
    noimg = false,
}

---远见
data.io_vision = {
    name = {cn = "远见", en = 'Farsightedness'},
    inspect = {cn = '看来眼睛大终究是有点好处的。', en = ''},
    recipe_desc = {cn = '以眼还眼！', en = ''},
    unlock = "eyeofterror",
    ingres = {
        milkywhites = 2,
    },
    onequip = function(inst, container, owner, params) 
        owner:AddCameraExtraDistance(container, params.tun.VISION * math.clamp(params.num, 0, params.tun.COUNT_LIMIT), params.name)
    end,
    onunequip = function(inst, container, owner, params) 
        if params.num <= 0 then
            owner:RemoveCameraExtraDistance(container, params.name)
        else
            owner:AddCameraExtraDistance(container, params.tun.VISION * math.clamp(params.num, 0, params.tun.COUNT_LIMIT), params.name)
        end
    end,
    noimg = false,
}

---荧光细菌
data.io_glowbacteria = {
    name = {cn = "荧光细菌", en = 'Fluorescent Bacteria'},
    inspect = {cn = '可共生在体内的菌群，发出微弱的生物荧光。', en = ''},
    recipe_desc = {cn = '提供微弱的光，真的很微弱！', en = ''},
    unlock = "lightflier",
    ingres = {
        lightbulb = 1,
    },
    prefabs = {
        "heatrocklight",
    },
    onequip = function(inst, container, owner, params) 
        if not container._light then container._light = {} end
        if not container._light[params.name] then 
            local light = SpawnPrefab("heatrocklight")
            light.entity:SetParent(container.entity)
            light.Light:SetRadius(params.tun.LIGHT_RADIUS)
            light.Light:SetIntensity(params.tun.LIGHT_INTENSITY)
            light.Light:Enable(true)
            container._light[params.name] = light
        end
    end,
    onunequip = function(inst, container, owner, params) 
        if params.num <= 0 then
            container._light[params.name]:Remove()
            container._light[params.name] = nil
        end
    end,
    noimg = false,
}

---发光诱饵
data.io_glowbait = {
    name = {cn = "发光诱饵", en = 'Glowing Bait'},
    inspect = {cn = '它完美的拟态被我完美地拟态了。', en = ''},
    recipe_desc = {cn = '黑暗中的生物自有智慧。', en = ''},
    unlock = "worm",
    ingres = {
        wormlight = 1,
    },
    prefabs = {
        "heatrocklight",
    },
    onequip = function(inst, container, owner, params) 
        if not container._light then container._light = {} end
        if not container._light[params.name] then 
            local light = SpawnPrefab("heatrocklight")
            light.entity:SetParent(container.entity)
            light.Light:SetRadius(params.tun.LIGHT_RADIUS)
            light.Light:SetIntensity(params.tun.LIGHT_INTENSITY)
            light.Light:Enable(true)
            container._light[params.name] = light
        end
    end,
    onunequip = function(inst, container, owner, params) 
        if params.num <= 0 then
            container._light[params.name]:Remove()
            container._light[params.name] = nil
        end
    end,
    noimg = false,
}

local function SetForcedNightVision(inst, nightvision_on)
    inst._forced_nightvision:set(nightvision_on)

    if inst.components.playervision ~= nil then
        if nightvision_on then
            inst.components.playervision:PushForcedNightVision(inst)
        else
            inst:DoTaskInTime(1,function(inst)
                inst.components.playervision:PopForcedNightVision(inst)
            end)
        end
    end

    -- The nightvision event might get consumed during save/loading,
    -- so push an extra custom immunity into the table.
    if nightvision_on then
        inst.components.grue:AddImmunity("light")
    else
        inst.components.grue:RemoveImmunity("light")
    end
end

local function nightvision_onworldstateupdate(owner)
    SetForcedNightVision(owner, (not TheWorld.state.isday) and (not TheWorld.state.isfullmoon))
end

---天眼
data.io_heaveneye = {
    name = {cn = "天眼", en = 'Eye of Heaven'},
    inspect = {cn = '原来祂的视角是这样的……', en = ''},
    recipe_desc = {cn = '从你从未有过的角度看世界。', en = ''},
    unlock = "alterguardian_phase2",
    ingres = {
        io_vision = 1,
        io_glowbait = 1,
        deerclops_eyeball = 1,
    },
    onequip = function(inst, container, owner, params) 
        if TheWorld ~= nil then
            if TheWorld:HasTag("cave") then
                SetForcedNightVision(owner, true)
            else
                owner:WatchWorldState("isdust", nightvision_onworldstateupdate)
                owner:WatchWorldState("isnight", nightvision_onworldstateupdate)
                owner:WatchWorldState("isfullmoon", nightvision_onworldstateupdate)
                nightvision_onworldstateupdate(owner)
            end
        end
    end,
    onunequip = function(inst, container, owner, params) 
        if params.num <= 0 and TheWorld ~= nil then
            if TheWorld:HasTag("cave") then
                SetForcedNightVision(owner, false)
            else
                owner:StopWatchingWorldState("isnight", nightvision_onworldstateupdate)
                owner:StopWatchingWorldState("isfullmoon", nightvision_onworldstateupdate)
                SetForcedNightVision(owner, false)
            end
        end
    end,
    noimg = false,
}

---绿手指
data.io_greenfinger = {
    name = {cn = "绿手指", en = 'Green Fingers'},
    inspect = {cn = '这算一种嫁接，还是算一种杂交？', en = ''},
    recipe_desc = {cn = '植物化躯体。', en = ''},
    unlock = "lordfruitfly",
    ingres = {
        plantmeat = 2,
    },
    onequip = function(inst, container, owner, params) 
        -- owner:AddTag("plantkin")
        owner:AddTag('io_greenfinger_ability')
    end,
    onunequip = function(inst, container, owner, params) 
        -- owner:RemoveTag("plantkin")  
        owner:RemoveTag("io_greenfinger_ability")
    end,
    noimg = false,
}
local function gainExtraLoot(target)
end
---金手指
data.io_goldenfinger = {
    name = {cn = "金手指", en = 'Hand of Midas'},
    inspect = {cn = '说到金手指，为什么那位国王没有被封在空气变成的金壳子里？', en = ''},
    recipe_desc = {cn = '点石成金，妙不可言。', en = ''},
    unlock = function(target)
        return target.prefab == "klaus" and target:IsUnchained()
    end,
    ingres = {
        klaussackkey = 1,
    },
    onequip = function(inst, container, owner, params)
        if not owner.kkd_goldenfinger then
            owner.kkd_goldenfinger = 0
        end
        owner.kkd_goldenfinger = owner.kkd_goldenfinger + params.tun.GOLDEN_PR
        owner.components.kkd_joinkill:SetTargetDeathFn('kkd_goldenfinger',function(target)
            if math.random() > owner.kkd_goldenfinger then return end
            if target and target.components.lootdropper then
                local loottable = {}
                for dep, _ in pairs(target.components.lootdropper:GetAllPossibleLoot(true)) do
                    table.insert(loottable,dep)
                end
                local key = math.random(1,#loottable)
                local j = 1
                for i, v in pairs(loottable)do
                    if j == key then
                        if v == 'butter' then
                            target.components.lootdropper:SpawnLootPrefab('milkywhites')
                        elseif v == 'krampus_sack' then
                            -- TODO
                        else
                            target.components.lootdropper:SpawnLootPrefab(v)
                        end
                        break
                    else
                        j = j + 1
                    end
                end
            end
        end)
    end,
    onunequip = function(inst, container, owner, params)
        owner.kkd_goldenfinger = owner.kkd_goldenfinger - params.tun.GOLDEN_PR
        if owner.kkd_goldenfinger <= 0 then
            owner.kkd_goldenfinger = nil
            owner.components.kkd_joinkill:RemoveTargetDeathFn('kkd_goldenfinger')
        end
    end,
    noimg = false,
}

-----真菌感染
--data.io_fungus_infection = {
--    name = {cn = "真菌感染", en = 'Fungus Infection'},
--    inspect = {cn = '', en = ''},
--    recipe_desc = {cn = '', en = ''},
--    unlock = "",
--    ingres = {
--        shadowheart = 1,
--        armor_sanity = 1,
--        nightsword = 1,
--    },
--    onequip = function(inst, container, owner, params)
--        -- TODO
--    end,
--    onunequip = function(inst, container, owner, params)
--        -- TODO
--    end,
--    noimg = false,
--}

---硬化表皮
data.io_hardenlayer = {
    name = {cn = "硬化表皮", en = 'Hardened Skins'},
    inspect = {cn = '坚不可摧！', en = ''},
    recipe_desc = {cn = '需要供能的防御方案。', en = ''},
    unlock = "mutatedbearger",
    ingres = {
        bearger_fur = 1,
        purebrilliance = 2,
        security_pulse_cage_full = 1,
    },
    onequip = function(inst, container, owner, params) 
        owner.components.health.externalabsorbmodifiers:SetModifier(container, params.tun.DMG_REDUCE, inst)
    end,
    onunequip = function(inst, container, owner, params) 
        owner.components.health.externalabsorbmodifiers:RemoveModifier(container, inst)
    end,
    noimg = false,
}

---霜冻踏地
data.io_froststep = {
    name = {cn = "霜冻踏地", en = 'Frost Step'},
    inspect = {cn = '凛冬已至，冰冷刺骨。', en = ''},
    recipe_desc = {cn = '一个反熵发生器。', en = ''},
    unlock = "mutateddeerclops",
    ingres = {
        deerclopseyeball_sentryward_kit = 1,
    },
    onequip = function(inst, container, owner, params)
        -- TODO
    end,
    onunequip = function(inst, container, owner, params)
        -- TODO
    end,
    noimg = false,
}

local natrue_damage = {
    acidrain = true,
    builder = true,
    hunger = true,
    hot = true,
    cold = true,
    fire = true,
    flower = true,
    marsh_bush = true,
    cactus = true,
    oasis_cactus = true,
    moonstorm_spark = true, -- 雨：月熠免疫
}

local function darkTrade(inst, data)
    if data then
        local attacker = data.attacker
        local weapon = data.weapon
        local cause = attacker == inst and weapon or attacker   -- 雨：模仿combat组件中对cause的定义，继承旧的其余逻辑
        -- local cause = data.cause
        local damage = data.damage
        if damage < 0 then
            if cause == nil or not natrue_damage[cause] then
                if inst ~= nil and inst:IsValid()
                and inst.components.health ~= nil and not inst.components.health:IsDead() then
                    -- c_announce(cause)
                    -- inst:RemoveEventCallback("attacked", darkTrade)  -- 避免进入第二次
                    inst.components.health:SetVal(0)   -- 雨：科雷的kill是不无视无敌的，碰到无敌状态下会进入死循环，栈溢出
                end
            end
        end
    end
end
---黑暗交易
data.io_darktrade = {
    name = {cn = "黑暗交易", en = 'Dark Trade'},
    inspect = {cn = '那么，代价是什么？', en = ''},
    recipe_desc = {cn = '一份契约，关于你死后灵魂的归属。', en = ''},
    unlock = "stalker_atrium",
    ingres = {
        shadowheart = 1,
        armor_sanity = 1,
        nightsword = 1,
    },
    onequip = function(inst, container, owner, params)
        if params.num == 1 and owner.components.combat then
            owner:ListenForEvent("attacked", darkTrade) -- 雨：改为监听combat组件的事件
            owner.components.combat.externaldamagemultipliers:SetModifier(container, params.tun.DMG_MULT, params.name)
        end
    end,
    onunequip = function(inst, container, owner, params)
        owner:RemoveEventCallback("attacked", darkTrade)
        if owner.components.health and owner.components.health:GetPenaltyPercent() < .5 then
            owner.components.health:SetPenalty(.5) -- 惩罚最多50%
            owner.components.health:DoDelta(0)
        end
        if params.num == 0 then
            owner.components.combat.externaldamagemultipliers:RemoveModifier(container,params.name)
        end
    end,
    noimg = false,
}


local function AddEnemyDebuffFx(fx, target)
    target:DoTaskInTime(math.random()*0.25, function()
        local x, y, z = target.Transform:GetWorldPosition()
        local fx = SpawnPrefab(fx)
        if fx then
            fx.Transform:SetPosition(x, y, z)
        end

        return fx
    end)
end

---噩梦附肢
data.io_artus_nightmare = {
    name = {cn = "噩梦附肢", en = ''},
    inspect = {cn = '我就是“谁在那！”里的那个“谁”。', en = ''},
    recipe_desc = {cn = '攻击肉体，同时攻击神志。', en = ''},
    unlock = iscrabkingwith("purplegem", 2),
    ingres = {
        purplegem = 2,
    },
    prefabs = {
        "battlesong_instant_panic_fx"
    },
    onequip = function(inst, container, owner, params) 
        container[params.name.."_pr"] = params.tun.PR * params.num
        initsth(container, params.name.."_onattack", function(target)
            if math.random() > container[params.name.."_pr"] then return end
            if target.components.hauntable ~= nil and target.components.hauntable.panicable then
                target.components.hauntable:Panic(params.tun.PANIC_TIME)
                AddEnemyDebuffFx("battlesong_instant_panic_fx", target)
            end
        end, function ()
            owner:ListenForEvent("onhitother", container[params.name.."_onattack"])
        end)
    end,
    onunequip = function(inst, container, owner, params) 
        container[params.name.."_pr"] = params.tun.PR * params.num
        if container[params.name.."_pr"] <= 0 then 
            owner:RemoveEventCallback("onhitother", container[params.name.."_onattack"])
            container[params.name.."_onattack"] = nil
        end
    end,
    noimg = false,
}

---敏捷附肢
data.io_artus_agility = {
    name = {cn = "敏捷附肢", en = 'Agile Appendages'},
    inspect = {cn = '唯快不破！', en = ''},
    recipe_desc = {cn = '为自己造一个“帮手”。', en = ''},
    unlock = iscrabkingwith("orangegem", 2),
    ingres = {
        orangegem = 2,
    },
    onequip = function(inst, container, owner, params) 
        owner.components.combat:SetAttackSpeedModifier(container, 1 + params.tun.ATK_SPEED_MULT * math.clamp(params.num,0,params.tun.COUNT_LIMIT), params.name)
    end,
    onunequip = function(inst, container, owner, params) 
        if params.num <= 0 then 
            owner.components.combat:RemoveAttackSpeedModifier(container, params.name)
        else
            owner.components.combat:SetAttackSpeedModifier(container, 1 + params.tun.ATK_SPEED_MULT * math.clamp(params.num,0,params.tun.COUNT_LIMIT), params.name)
        end
    end,
    noimg = false,
}

---巧手附肢
data.io_artus_handy = {
    name = {cn = "巧手附肢", en = ''},
    inspect = {cn = '它总能为我留下一些可利用的边角料。', en = ''},
    recipe_desc = {cn = '高效建造助手', en = ''},
    unlock = iscrabkingwith("greengem", 2),
    ingres = {
        greengem = 2,
    },
    onequip = function(inst, container, owner, params) 
        container[params.name.."_pr"] = params.tun.PR * math.clamp(params.num, 0, params.tun.COUNT_LIMIT)
        initsth(container, "_old_build_removegredientsfn", owner.components.builder.RemoveIngredients, function()
            owner.components.builder.RemoveIngredients = function(...)
                if math.random() < container[params.name.."_pr"] then return end 
                if container._old_build_removegredientsfn then container._old_build_removegredientsfn(...) end
            end
        end)
    end,
    onunequip = function(inst, container, owner, params) 
        container[params.name.."_pr"] = params.tun.PR * math.clamp(params.num, 0, params.tun.COUNT_LIMIT)
        if container[params.name.."_pr"] <= 0 then 
            if container._old_build_removegredientsfn then 
                owner.components.builder.RemoveIngredients = container._old_build_removegredientsfn
                container._old_build_removegredientsfn = nil 
            end
        end
    end,
    noimg = false,
}

---能量附肢
data.io_artus_energy = {
    name = {cn = "能量附肢", en = ''},
    inspect = {cn = '能量在它体内涌动！', en = ''},
    recipe_desc = {cn = '警告：使用时须持有高级电工证。', en = ''},
    unlock = iscrabkingwith("opalpreciousgem", 2),
    ingres = {
        opalpreciousgem = 2,
    },
    prefabs = {
        "electricchargedfx",
    },
    onequip = function(inst, container, owner, params) 
        if owner.components.electricattacks == nil then
            owner:AddComponent("electricattacks")
        end
        owner.components.electricattacks:AddSource(container)
        if container._onattackother == nil then
            container._onattackother = function(attacker, data)
                if data.weapon ~= nil then
                    if data.projectile == nil then
                        --in combat, this is when we're just launching a projectile, so don't do FX yet
                        if data.weapon.components.projectile ~= nil then
                            return
                        elseif data.weapon.components.complexprojectile ~= nil then
                            return
                        elseif data.weapon.components.weapon:CanRangedAttack() then
                            return
                        end
                    end
                    if data.weapon.components.weapon ~= nil and data.weapon.components.weapon.stimuli == "electric" then
                        --weapon already has electric stimuli, so probably does its own FX
                        return
                    end
                end
                if data.target ~= nil and data.target:IsValid() and attacker:IsValid() then
                    SpawnPrefab("electrichitsparks"):AlignToTarget(data.target, data.projectile ~= nil and data.projectile:IsValid() and data.projectile or attacker, true)
                end
            end
            container:ListenForEvent("onattackother", container._onattackother, owner)
        end
        SpawnPrefab("electricchargedfx"):SetTarget(owner)
    end,
    onunequip = function(inst, container, owner, params) 
        if owner.components.electricattacks ~= nil then
            owner.components.electricattacks:RemoveSource(container)
        end
        if container._onattackother ~= nil then
            container:RemoveEventCallback("onattackother", container._onattackother, owner)
            container._onattackother = nil
        end
    end,
    noimg = false,
}

---碎心者
data.io_heartbreaker = {
    name = {cn = "碎心者", en = ''},
    inspect = {cn = '触及灵魂的痛楚……', en = ''},
    recipe_desc = {cn = '还是别把这个带给她了。', en = ''},
    unlock = iscrabkingwith("hermit_pearl", 1),
    ingres = {
        hermit_cracked_pearl = 1,
    },
    onequip = function(inst, container, owner, params) 
        if not owner.components.planardamage then 
            owner:AddComponent("planardamage")
        end
        owner.components.planardamage:AddBonus(container, params.tun.ADD_PLANAR_DAMAGE, inst)
    end,
    onunequip = function(inst, container, owner, params) 
        if owner.components.planardamage then 
            owner.components.planardamage:RemoveBonus(container, inst)
        end
    end,
    noimg = false,
}


-------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------                LAN's IDEA                  ----------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------

local function oncancelall(tbl)
    if tbl.stoptask then
        tbl.stoptask:Cancel()
        tbl.stoptask = nil
    end
    if tbl.healtask then
        tbl.healtask:Cancel()
        tbl.healtask = nil
    end
    if tbl.cir then 
        tbl.cir:Remove()
        tbl.cir = nil 
    end
end

local function onupdate(tbl, params)
    tbl.radius = params.tun.PER_RADIUS * params.num 
    tbl.heal = params.tun.HEALING_PERCENT * params.num * params.tun.PERIOD
    if tbl.healtask then
        tbl.healtask:Cancel()
        tbl.cir:Remove()
        tbl.onheal()
    end
end

-----愈疗真菌
--data.io_heal_mushroom = {
--    name = {cn = "愈疗真菌", en = 'Healing Fungi'},
--    inspect = {cn = '', en = ''},
--    recipe_desc = {cn = '', en = ''},
--    unlock = {
--        "toadstool",
--        "toadstool_dark",
--    },
--    ingres = {
--        shroom_skin = 2,
--        green_cap = 6,
--    },
--    prefabs = {
--        "fx_io_circle",
--        "cane_ancient_fx",
--    },
--    onequip = function(inst, container, owner, params)
--        local tbl = params.name.."_task"
--        local function onheal()
--            --TheNet:Announce("stand still")
--            --circle
--            local function io_heal_mushroom_circle(r)
--                local fx = SpawnPrefab('fx_io_circle')
--                fx.AnimState:SetMultColour(.1,.6,.1,.9)
--                local scale = .25 * r
--                fx.Transform:SetScale(scale,scale,scale)
--                return fx
--            end
--            container[tbl].cir = io_heal_mushroom_circle(container[tbl].radius)
--            container[tbl].cir.entity:SetParent(owner.entity)
--            --fx and heal
--            if container[tbl].healtask then container[tbl].healtask:Cancel() end
--            container[tbl].healtask = container:DoPeriodicTask(params.tun.PERIOD, function()
--                local x, y, z = owner.Transform:GetWorldPosition()
--                --fx
--                local genpoint = COORDS_kukude:GenPointInCircle(x,z,container[tbl].radius)
--                local function io_heal_mushroom_fx_incircle(r)
--                    local num = math.max(1,math.floor(r^2 - 2*r)+math.random(r))
--                    for i=1,num do
--                        local x,z = genpoint()
--                        local fx = SpawnPrefab('cane_ancient_fx')
--                        fx.Transform:SetPosition(x,0,z)
--                    end
--                end
--                io_heal_mushroom_fx_incircle(container[tbl].radius)
--
--                --heal
--
--                local ents = TheSim:FindEntities(x, y, z, container[tbl].radius, nil, {"wall","structure","INLIMBO"})
--                table.insert(ents, owner)
--                for n, ent in pairs(ents) do
--                    if ent:IsValid() and owner.components.combat:IsAlly(ent) and ent.components.health and not ent.components.health:IsDead() then
--                        local max = ent.components.health:GetMaxWithPenalty()
--                        ent.components.health:DoDelta(max * container[tbl].heal, true)
--                    end
--                end
--            end)
--        end
--        local function onlocomote()
--            --wait for a frame
--            container:DoTaskInTime(0,function()
--                if not owner.components.locomotor.isupdating then
--                    --TheNet:Announce("on stop")
--                    if not container[tbl].stoptask and not container[tbl].healtask then
--                        container[tbl].stoptask = container:DoTaskInTime(params.tun.STANDSTILL_TIME, onheal, 0)
--                    end
--                else
--                    --TheNet:Announce("on move")
--                    oncancelall(container[tbl])
--                end
--            end)
--        end
--        initsth(container, tbl, {}, function()
--            container[tbl].onlocomote = onlocomote
--            container[tbl].onheal = onheal
--            container:ListenForEvent("locomote", onlocomote, owner)
--            --onequip
--            onlocomote()
--        end)
--        onupdate(container[tbl], params)
--    end,
--    onunequip = function(inst, container, owner, params)
--        local tbl = params.name.."_task"
--        if params.num <= 0 then
--            container:RemoveEventCallback("locomote", container.onlocomote, owner)
--            oncancelall(container[tbl])
--            container[tbl] = nil
--        else
--            onupdate(container[tbl], params)
--        end
--    end,
--    noimg = false,
--}







local function unlock(tbl)
    return function(target)
        for _, name in pairs(tbl) do 
            if target.prefab == name then return true end 
        end
        return false
    end
end


for prefab, pdata in pairs(data) do 
    pdata.inspect = pdata.inspect or pdata.name 
    pdata.recipe_desc = pdata.recipe_desc or pdata.name
    -- local old = pdata.unlock
    -- pdata.unlock = (type(old) == 'table' and unlock(old)) or (type(old) == 'string' and unlock({old})) or old
    local old_on = pdata.onequip
    pdata.onequip = function(inst, container, owner)
        local _, num = container.components.container:Has(prefab, 0)
        old_on(inst, container, owner, {name = prefab, tun = TUNING.MOD_KUKUDE.IO[string.upper(string.sub(prefab,4))], num = num})
        owner.components.sanity.max = owner.components.sanity.max - TUNING.MOD_KUKUDE.IO.SAN_EQUIP
        owner.components.sanity:DoDelta(0)
    end
    local old_un = pdata.onunequip
    pdata.onunequip = function(inst, container, owner)
        local _, num = container.components.container:Has(prefab, 0)
        old_un(inst, container, owner, {name = prefab, tun = TUNING.MOD_KUKUDE.IO[string.upper(string.sub(prefab,4))], num = num})
        if container._opened_by_scalpel then inst.components.finiteuses:Use(TUNING.MOD_KUKUDE.IO.FINITEUSE) end
        owner.components.sanity.max = owner.components.sanity.max + TUNING.MOD_KUKUDE.IO.SAN_EQUIP
        owner.components.sanity:DoDelta(0)
    end
end

return data